﻿#include "ConfigFileReadWrite.h"

//3.获得配置文件的有效行数；
int getLines_ConfigFile(FILE* file)
{
	char buf[1024] = { 0 };
	int lines = 0;
	while (fgets(buf, 1024, file) != NULL)
	{
		if (!isValid_ConfigFile(buf))
		{
			continue;
		}
		memset(buf, 0, 1024);
		++lines;
	}

	//15.把文件指针file重置到文件的开头；
	fseek(file, 0, SEEK_SET);

	return lines;
}
//4.加载配置文件；
void loadFile_ConfigFile(const char* filePath, char*** fileData, int* line)
{
	FILE* file = fopen(filePath, "r");
	if (NULL == file)
	{
		return;
	}

	int lines = getLines_ConfigFile(file);
	//9.给每行数据开辟内存；
	char** temp = malloc(sizeof(char*) * lines);
	char buf[1024] = { 0 };
	int index = 0;
	while (fgets(buf, 1024, file) != NULL)
	{
		//10.如果返回false，即该行数据无效，就跳过这一行；
		if (!isValid_ConfigFile(buf))
		{
			continue;
		}

		temp[index] = malloc(strlen(buf) + 1);
		strcpy(temp[index], buf);
		++index;

		//12.清空buf；用temp[index]记录下该行数据；
		memset(buf, 0, 1024);
	}

	fclose(file);

	*fileData = temp;
	*line = lines;
}
//5.解析配置文件；
void parseFile_ConfigFile(char** fileData, int lines, struct ConfigInfo** info)
{
	struct ConfigInfo* myInfo = malloc(sizeof(struct ConfigInfo) * lines);
	memset(myInfo, 0, sizeof(struct ConfigInfo) * lines);

	for (int i = 0; i < lines; ++i)
	{
		//16.获取到冒号: 的位置；
		char* pos = strchr(fileData[i], ':');

		//17.将冒号前的字符串，拷贝给myInfo[i].key，pos-fileData[i]就是要拷贝的字符个数；
		strncpy(myInfo[i].key, fileData[i], pos - fileData[i]);
		//18.pos+1指针pos直接就指到这行数据的末尾，也就是\n。拷贝的时候，不需要拷贝\n，所以拷贝个数要减去1；
		strncpy(myInfo[i].val, pos + 1, strlen(pos + 1) - 1);

		printf("19.输出该行数据的key：%s  val：%s\n", myInfo[i].key, myInfo[i].val);
		//key：ip  val：127.0.0.1
		//key：port  val：8080
		//key：username  val：root
		//key：password  val：admin
		//key：ppp  val：hello world
		//key：aaa  val：bbb
	}

	//22.释放文件信息；
	for (int i = 0; i < lines; ++i)
	{
		if (fileData[i] != NULL)
		{
			free(fileData[i]);
			fileData[i] = NULL;
		}
	}


	*info = myInfo;
}
//6.获得指定配置信息；
char* getInfo_ConfigFile(const char* key, struct ConfigInfo* info, int line)
{
	for (int i = 0; i < line; ++i)
	{
		if (strcmp(key, info[i].key) == 0)
		{
			return info[i].val;
		}
	}
	return NULL;
}
//7.释放配置文件信息；
void destroyInfo_ConfigFile(struct ConfigInfo* info)
{
	if (NULL == info)
	{
		return;
	}
	free(info);
	info = NULL;
}
//8.判断当前行是否有效；
int isValid_ConfigFile(const char* buf)
{
	//13.strchr()查找字符串buf中，是否有:，没有就得到NULL；
	if (buf[0] == '#' || buf[0] == '\n' || strchr(buf, ':') == NULL)
	{
		return 0;
	}
	return 1;
}